This page last changed on Apr 29, 2010 by aunger.

On Linux you can easily use Xvfb to set up virtual displays to use during testing that requires a graphical environment to be available.

First, install Xvfb. You will also want some sort of window manager so that you get things like Window menus and keyboard command accelerators. We're using xfwm4 for this.

On Redhat/Fedora systems, run: (you may need to enable or install 3rd party repos like Rpmforge and/or EPEL)

Unable to find source-code formatter for language: shell. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
sudo yum install xorg-x11-server-Xvfb xfwm4

Now you need some way to start and manage Xvfb. We're using an init.d style script to accomplish this:

Unable to find source-code formatter for language: shell. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
#!/bin/sh

# Source function library.
. /etc/rc.d/init.d/functions

SERVER_NUM="$2"
USER=maven
HUDSON_HOME=/web/hudson.dev.concord.org
LOG="$HUDSON_HOME/hudson-xvfb-${2}.log"
LOCK="/var/lock/subsys/hudson-xvfb${2}"
export HUDSON_HOME 

RETVAL=0

pid_of_hudson_xvfb() {
  ps auxwww | grep Xvfb | grep ":${SERVER_NUM}" | grep -v grep | awk '{print $2}'
}

start() {
  [ -e "$LOG" ] && cnt=`wc -l "$LOG" | awk '{ print $1 }'` || cnt=1

  echo -n $"Starting hudson xvfb ${SERVER_NUM}: "

  echo "" > "$LOG"
  chown $USER $LOG
  cd "$HUDSON_HOME"

  # start Xvfb
  CMD="nohup /usr/bin/Xvfb :${SERVER_NUM} -screen 0 1600x1200x16 -ac -x XTEST >> ${LOG} 2>&1 &"
  su -m --command="${CMD}" ${USER}
  sleep 2

  # start a window manager
  CMD="DISPLAY=:${SERVER_NUM} nohup xfwm4 &"
  su -m --command="${CMD}" ${USER}
  sleep 2


  pid_of_hudson_xvfb > ${HUDSON_HOME}/hudson-xvfb${SERVER_NUM}.pid
  RETVAL=$?
  [ $RETVAL = 0 ] && success $"$STRING" || failure $"$STRING"
  echo

  [ $RETVAL = 0 ] && touch "$LOCK"
}

stop() {
  echo -n "Stopping hudson xvfb ${SERVER_NUM}: "

  pid=`pid_of_hudson_xvfb`
  [ -n "$pid" ] && kill $pid
  RETVAL=$?
  cnt=10
  while [ $RETVAL = 0 -a $cnt -gt 0 ] &&
        { pid_of_hudson_xvfb > /dev/null ; }
  do
      sleep 1
      ((cnt--))
  done

  [ $RETVAL = 0 ] && rm -f "$LOCK"
  [ $RETVAL = 0 ] && success $"$STRING" || failure $"$STRING"
  echo
}

status() {
  pid=`pid_of_hudson_xvfb`
  if [ -n "$pid" ]; then
      echo "hudson xvfb :${SERVER_NUM} (pid $pid) is running..."
      return 0
  fi
  if [ -f "$LOCK" ]; then
      echo $"${base} dead but subsys locked"
      return 2
  fi
  echo "hudson xvfb :${SERVER_NUM} is stopped"
  return 3
}


# See how we were called.
case "$1" in
start)
  start
  ;;
stop)
  stop
  ;;
restart)
  stop
  start
  ;;
status)
  status
  ;;
*)
  echo $"Usage: $0 {start|stop|restart|status} num"
  exit 1
esac

exit $RETVAL

You can then use the script to start, stop, restart and check the status of each display:

Unable to find source-code formatter for language: shell. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
hudson-xfvb.sh start display_num
hudson-xfvb.sh stop display_num
hudson-xfvb.sh restart display_num
hudson-xfvb.sh status display_num

This script can't actually be used at system startup because it expects to get a view number passed in to it, and init.d doesn't support that (afaik). So instead, add a few lines to /etc/rc.local:

Unable to find source-code formatter for language: shell. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
# start 3 screens, numbered 4-6
/path/to/hudson-xfvb.sh start 4
/path/to/hudson-xfvb.sh start 5
/path/to/hudson-xfvb.sh start 6

Now to use these screens from within Hudson, just make sure you set the DISPLAY environment variable in your build settings or node settings.

Unable to find source-code formatter for language: shell. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
DISPLAY=localhost:4
Document generated by Confluence on Jan 27, 2014 16:52